package com.yangli;

import com.yangli.ahies.study.util.DoubleNode;
import com.yangli.leecode.mashib.*;
import com.yangli.leecode.mashib.code.*;
import com.yangli.leecode.mashib.DynamicProgramming;
import com.yangli.leecode.mashib.Recursion;
import com.yangli.leecode.mashib.code.Code05_UnionFind;
import com.yangli.leecode.mashib.*;
import com.yangli.leecode.mashib.code.*;
import com.yangli.leecode.mashib.graph.Graph;
import com.yangli.leecode.mashib.interview.TwentySeven;
import com.yangli.leecode.mashib.interview.TwentyTwo;
import com.yangli.leecode.mashib.unionSet.UnionSet;

/**
 * @Description
 * @Author liyang
 * @Date 2023/4/28 14:50
 */
public class Text {
    public static void main(String[] args){
    }
    /**学习笔记  左神leecode https://www.bilibili.com/video/BV13g41157hK?p=3&vd_source=ee264bd7d696e9474b767a0b28f15164
P3 认识复杂度和简单排序算法
    一个操作如果和样本数据量没有关系，每次都是固定时间内完成操作，叫做常数操作。表达式中只要高阶项，不要低阶项，也不要高阶项的系数。评价一个算法好坏，先看时间复杂度指标，然后一样在看常数项时间。
    类似的空间复杂度。O最差情况下复杂度==>还有表示平均情况下复杂和最优情况下复杂度
    冒泡排序：最大的到最后 选择排序：最小的排在最前面 插入排序：索引位置之前的排序号，后面新增需要排序的
                              时间复杂度   空间复杂度    稳定性（a=b,a和b不会交换） 最好数据情况下的时间复杂度
                    选择排序    O(N^2)      O(1)        无       O(N^2)
                    冒泡排序    O(N^2)      O(1)        有       O(N^2)
                    插入排序    O(N^2)      O(1)        有       O(N)
                    归并排序    O(N*logN)   O(N)        有       O(N)
                    快速排序    O(N*logN)   O(logN)     无       O(N*logN)==>最差情况O(N^2),每次快排只能解决一个数，快排在这之间。
                    堆排序      O(N*logN)   O(1)        无       O(N*logN)
                    计数排序    O(N+k)      O(N+k)
                    基数排序    O(N*k) k表示数字长度

     异或运算 ==>无进位相加 位运算异或 0^a=a a^a = 0 tip:1 实现a,b交换 a= a^b; b=a^b; a=a^b;2数组 某个数奇数次，其他都是偶数，找出这个数 3获取int a最右侧的1=> a&(~x+1) 4不用额外空间交换两个数，前提是两个数不相等
     异或运算 ☆ 一个数组，有两种数出现了奇数次，其他数出现了偶数次，找出这两种数==> 异或结果不为0，找出最右侧1进行分组，分组异或出来的结果就是a和b
     二分法 有序数组查找数组是否存在;有序数据，寻找>=某个数最左的位置(跟前面的区别就是一定会二分结束，需要变量记录最小值);局部最小值 二分法，先判断头尾，选择中间的两便，进行二分    序数组 num位置 二分法  大于num最左的位置 二分法 大于num 保存位置
     无序相邻不等数组 局部最小 判断头尾，只能较大否则返回，查找中间，如果是局部小返回中间，否则肯定有大于一边，从一边再二分。二分小技巧:(l+r)/2==>l+(r-l)/2==>l+(r-l)>>1
     对数器 想要测的方法a=> 实现复杂度不好但容易实现的方法b 小范围随机数尝试。
 P4 认识log^n*n的排序
     估计特殊递归行为的时间复杂度:master公式==>前提子问题是等规模的，才能使用mater公式
     T(N) = a*T(N / b) + O (N^d)
     a表示生成的子问题数（比如二叉树的递归遍历就是 a = 2）；b表示每次递归是原来的1/b的规模，O(N^d) 表示除了递归过程之外其他调用的时间复杂度。 若生成的子问题规模不相同，比如T(N) = T(N / 2) + T(N / 3) + O (N^d)，那么便不能用这个公式计算。
     log(b,a) < d	O(N ^ d)
     log(b,a) > d	O(N ^ log(b,a))
     log(b,a) = d	O((N^d) * logN)1
     归并排序：递归左边有序右边有序，整体有序，使用辅助数组合并.比较信息没有浪费，实质是把比较行为变成了有序信息的传递。==>利用master公式::log^n*n 下面两个问题都是归并排序扩展==>precess(arr,L,R) mid = (l+r)>>1  precess(arr,L,mid)+precess(arr,mid,r)+merge(arr,l,mid,r)
     小和问题：左边比当前数小的数的和的统计==>右边有几个比当前数大，n*当前数的和==>归并排序左右两边merge过程中，统计右边大于左边每个数的个数N，边界相减，ans+=左边的数*N
     逆序对问题：一个数组中左边的数比右边的数大，则这两个数构成逆序对，打印所有逆序对。
     快速排序三个版本 1，随机选择一个数作为基准，并放到最后，只有左指针。2，三色荷兰问题，返回左右边界指针，有左右指针。3，每次随机选择数组中的数再进行递归 ==>不稳定，选择的数并不能把数组分割成两半，有可能退化为O(N平方)，每次快排只能处理一个数。
 P5 详解堆排序以及排序内容总结
    完全二叉树 用数组表示根节点为0 则i节点左节点位置 2*i+1 右节点位置 2*i+2 父节点为 （i-1）/2 根节点从1开始 2*i==> i<<1 2*i+1==> i<<1|1 i/2==>i>>1
    堆是一种特殊完全二叉树，节点比子节点要大或者小，子树最大或者最小都在根节点。heapInsert:插入数据跟根节点比较如果是需交换，如果需要交换向上递归，不满足条件或者跟节点停止。heapify:删除头节点，用尾节点放到头节点，子节点选择较大（小）值交换并向下递归交换。
    堆排序：heapSrot==>先进行heapInsert（N*logN），然后从最后位置开始heapify（N*logN）；堆排序 数据一个一个给你，从上到下的方法N*logN，如果整个数组给你，从下到上进行排序复杂度为O(N)==>最后一层N/2不用操作，上面一次只需要操作一次，只需要进行遍历一遍数据。
    java的堆就是权限队列【PriorityQueue】堆排序扩展==>有一个接近有序的数据，数据移动不超过K个数。如何排序==>N*logK 用有序队列初始前K元素，弹出最小根,由于不需要移动k位置，前k元素一定包含最小数，然后依次加入元素
    比较器 重载比较运算符==>灵活，泛型编程 =>返回正数表示，第二个参数放在前面或者上面 堆实现resize方法，设置值之后更新堆。要保存数据的位置
    之前的几种都是基于比较的排序，不基于比较的排序，需要一定的数据状况==>都有稳定性
       计数排序:数据在一定范围上，进行词频统计
       基数排序:适用于数字的情况。准备0-9十个桶，按照个位数把数字放到对应的桶里面，按照0-9取出，再依次按照十位数百位数放入桶再取出。位数高的数字优先级低。基数排序实现，使用词频数组和辅助数组，每次遍历确定位置。
    无稳定性：选择排序  快速排序  堆排序 有稳定性：冒泡排序 插入排序 归并排序==>目前没有找到时间复杂度为N*logN,既稳定且空间复杂O（1）的比较排序
    常见的坑：1,归并排序的空间复杂度变成O（1），但是丧事稳定性。比较难，搜索归并排序内部缓存法。2,‘原地归并排序’也可以让空间复杂度变成O（1）,但是空间复杂变成n^2.3,快速排序可以做到稳定性，但是空间复杂度上升到O（N），搜索‘O1stable sort’。4，目前没有找到时间复杂度为N*logN,既稳定且空间复杂O（1）的比较排序
            5，一个数组奇数放左边，偶数放右边，且不改变数字相对次序（稳定性）==>‘O1stable sort’,经典快排就是01标准，大于某个数或者小于某个数，奇偶数也是01标准，在N*logN情况下做不到稳定性。==>类似4可以做到，空间复杂度上升。
     工程上改进：在样本量小于 60 的时候使用插入排序，对比冒泡排序和选择排序，插入排序的时间复杂度是受数据状况影响的，范围是 [O(n), O(n^2)] ， 而且其代码简洁，常数项低；样本量大于 60 的时候，在能使用快排的场景下，如不用区分数据的差异，不追求稳定性，这时选用快排，因为其非常简洁，操作少，常数项低；需要区分数据的差异，要求算法具有稳定性的时候使用归并排序。
 P6 链表
    哈希表和有序表在使用层面上都可以理解为一种集合结构
    哈希表有key无value::hashSet||有key有value::hashMap，操作的复杂度都是常数，放入的东西如果基础类型，值传递，占用空间为基础类型大小。如果是引用类型，引用传递，占用空间为引用大小，大小一般为8字节。
    有序表有key无value::treeSet||有key有value::treeMap,sbt，avl树，红黑树，跳表都属于有序表。（AVL自平衡二叉树 SB数  红黑树  跳跃表 空间换时间，建立索引）avl的平衡根据层级，左右层级查不能高于1 sb平衡根据左右节点数量 红黑树通过增加层级误差减少左旋右旋 几个数的差异都是常数级别差异，总的时间复杂度都是logn
    下面的几个方法要求的空间复杂度都是O（1）:
     反转单向链表和双向链表 {@link MaxWidthRamp#reverseListNode} {@link MaxWidthRamp#reverseDoubleNode(DoubleNode)}
     打印两个有序链表的公共部分【有序】==>判断是否相等，不相等比较大小让某一个进行next
     判断一个链表是否为回文结构==>反转之后，判断相等
     让链表根据某个值划分成小于等于大于某个值的顺序链表==>申请小于某值的head和tail:申请等于某值的head和tail:申请大于某值的head和tail
     包含随机指针链表的复制==>1.使用额外空间的方法。用map存放旧节点的复制，遍历老链表节点，取出对应新节点，获取老节点对应的新节点的next和rand指正的。2，老节点后面插入新节点，关联起来，通过lodNode.rand.next找到新节点的rand
     两个链表相交第一个节点==>最简单办法使用hashSet，一一比较相等则为第一个节点。正确解法==>0,找出链表中有闭环的第一个节点 1，无闭环。分别遍历，算出长度差值，长链表先走差值步数，然后一一比较相等则为第一个节点。2，有闭环两种情况，闭环在环里面和外面
     约瑟夫环  f(n,m) n表示环中多少人 m表示第几个出局，则f(n.m)最后出局的人在n个人环中，m出局的位置，位置应该再（0，n-1）上。并且有如下规则 f（n，m）= (f(n-1,m)+m)%n
 P7 二叉树
     {@link TreeNode} {https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class13/Code02_MaxSubBSTHead.java}
     一个按序满二叉树的递归序：124442555213666377731 先中右表示头的位置，也标识在递归序中取第几次出现的值
     先序遍历:先头再左右 1245367 中序遍历：先左再头右4251637 后序遍历：左右头4526721
     用递归方式或者非递归（栈或者队列）方式实现序遍历
     二叉树递归递归套路，分别从左右收集需要的定义信息，比如层高，是否满足某种条件=>X参与和x不参与
        二叉树是否是平衡术==>左数右数平衡，且树高差不大于1
        二叉树的最大距离==> info：树高和最大距离
        info:最大值最小值最大搜索树节点数是否搜索树
        info:来最大快乐 不来最大快乐
        纸条对折==>找到这个二叉树递归规律，初始节点down，down，up，进行中序遍历
 P8 图
     {@link Graph}   点集 边集 有向图 无向图==>双向有向图==>图的表示，邻接表示法（以点为基础） 矩阵表示法（以边为基础）==>通过统一的转化，把图转化成统一对象 node value in out nexts edges
     bfs 宽度（广度）优先遍历，距离我进的先遍历==>队列+set 队列 控制当前节点和下一个节点 set控制那些已经注册过了，防止循环 队列弹出元素使用元素
     dfs 深度优先遍历，一条路走到底==>栈+set（控制循环） 栈加入元素使用元素
     图的拓扑排序 前提 有向图且无环 一个节点依赖前一个节点或者多个节点==>优先寻找入度为0的节点，并消除节点作为其他节点入度，找下一个 准备一个map存放节点和他的入度数 遍历入度为0的集合
     并查集结构{@link Code05_UnionFind} https://github.com/algorithmzuo/algorithmbasic2020/tree/master/src/class16
     最小生成树 kruskal==> 所有边集排序遍历+并查集进行合并点
     最小生成树 P算法==>某个点出发,点加入set，解锁边加入小根堆，选取最小边添加到结果集，如果有新点加入set，解锁新点新解锁的边到小根堆。从小根堆选择最小，出发如此以往。相当于每次选择边加入了新的点，一个点一个点加不需要并查集，如果不是新的点就不要了
     Dijkstra dj算法 边为正数即每次路径都有加权 求最短路径==>TSP 图是全连接，从出发点回到出发点，其他点只能一次，距离一次
     a起点  到所有点的最短距离表 小根堆==>自定义实现堆
P9 详解前缀树和贪心算法
     前缀树（字典树） {@link Code02_Trie} pass 经过 end 结束 nextNode 为空则表示结束  统计这个字符以某个字符出现的次数 这个字符有没有出现 =>增加搜索删除==>实现方式 固定数组或者hash表
     贪心算法：局部最优推到整体最优，更多的题目都是经验和常识。暴力解一般都是递归，前一种的情况往后面递归，还要注意递归的时候回来的时候需要恢复现场。
     会议安排最优解==>暴力解法:每次用剩余会议，已经安排数据，会议截止时间进行递归==>贪心算法：最优解 结束时间越早的有限安排，每次排会议也是先判断某个会议时间是否大于上个会议截止时间
     切金条==>暴力解法 遍历数据，从i=0开始切，向下递归，传参是剩余未分割大小和消耗金币，返回最小金币 {@link GoldCut}
     利润最大问题，花费，利润，k项目数量限制，m初始资金==>先把项目根据投入加入小根堆，弹出符合初始资金的项目，加入以利润为基础的大根堆，选择利润最大根，循环K次，初始资金加上最大利润{@link Code04_IPO}
     放灯的问题
     一个数据流中，随时可以取得中位数==>大根堆+小根堆，两个堆数据量差不大于2，要求大根堆的数都小于小根堆的数，这样两个堆顶就是中位数了
 P10 暴力递归
     大问题拆除同类问题的小问题，到basecase，得子问题后的决策，返回需要的解而不是每一个问题解==>不记录每个问题的解是暴力递归，记录每个问题的解是动态规划
     汉诺塔问题==>n从左到右分为三步 第一步，n-1从左到中 第二步 第n个移动到右 第三不 n-1从中移动到右 ==>2*f(n-1) +1==> 2^n-1+2^n-2+....1==>2^N-1
     穷举字符数组的子序列==>每个位置上字符就两种选择要和不要
     打印所有子序列（递归四个参数1，原始字符数组 2，递归到数组索引 3，当数组递归完收集字符串的集合 4，前面递归路径 ）==>子串连续顺讯的元素 子序列可以不连续，但是顺序不能乱（比子串要多）
     打印所有子序列，不出现重复字面值的子序列==>收集的时候用set去重就可以了
     打印字符全排列，去重==>分支限界
     先后手拿牌 {@link  Recursion#win}  &&范围尝试模型
     反转栈且不适用额外空间==>{@link  ReverseStack}
     1对A...26对应Z  从左到右尝试行为 {@link  Recursion#translateNum1 translateNum2}
     经典背包 两个数组表示重量和价值，如何在重量限制下最大价值{@link  Recursion#choose}
P11 暴力递归补充
     N皇后问题 {@link Recursion#queen #bitQueen}
P12 基础提升-哈希函数和哈希表
     经典哈希函数：输入无穷，输出有限，md5==>0-2^64-1(16长度16进制) sha1=>0-2^128-1
                samein==>sameout 不随机
                difin==>sameout 函数碰撞
                均匀性（离散型）==>离散型约好 哈希函数约好
     哈希表：java虚拟机，离线扩容技术，流量切换;开放地址法，用固定数组存储元素
     实现一个哈希表，新增删除和随机获取元素方法否是O(1)，使用两个map，存放元素和索引：：索引和元素，在size上随机获取，删除之后用最后元素填上删除的洞
     布隆过滤器：不需要删除，只需要大数据的内存查询==>位图 使用基本数量类型==>把元素经过k个hash函数进行m取模，到m-1位置赋值为1.对元素采集k个特点，在m长度的位图上记录。n 样本量 p失误率 m（位图长度）=-（n*lnP）/（ln2）^2  k(哈希函数 向上取正)=ln2*（m/n） p（真） = （1-e^-(n*k)/m）^k
     一个int4字节，32位。现在有一个320位位图，new int[10]，如何找到第178位。int numIndex = 178/32; int bitIndex = 178%32; int s  = ((arr[numIndex]>>(bitIndex)&1);
     key关键值经过k个hash函数得到值，每个hash值对长度m位图取模，对应的位置设置为1==>只会设置成1，如何比较，key进行过k个kash所在位置是不是为1. 不允许删除，允许一定失误率
     一致性哈希+虚拟节点==>redis槽 16553个点
P13 基础提升-有序表和并查集
     有序表：treeSet 数据有序 无序表：hashmap 顺序表：数组或者队列 堆：PriorityQueue
     hashMap==>hash表，无序表;O(1)  有序表key有序==>treeMap O(logN)  （AVL自平衡二叉树 SB数  红黑树  跳跃表 空间换时间，建立索引）avl的平衡根据层级，左右层级查不能高于1 sb平衡根据左右节点数量 红黑树通过增加层级误差减少左旋右旋 几个数的差异都是常数级别差异，总的时间复杂度都是logn
     矩阵中的岛==>定义函数infect，会把邻近的1变成2，调用几次就是几个岛 {@link TwentySeven#shortestBridge(int[][])}
     {@link UnionSet}==>对于上面矩阵中的岛的问题，如果是超级大的矩阵，需要分割矩阵，单独计算每个小矩阵的岛数量和边界，利用并查集合并其他矩阵减去有连通性的数量就是合并矩阵的岛数量。==>类似mapreduce过程
P14 基础提升-KMP和Manacher算法
     kmp算法:字符串str1和str2，如果str1包含str2，返回包含str2的开始位置，O（n）。{@link Code_KMP} 利用前后缀辅助数组加速，复杂度下降
     Manacher:最长回文子串长度 O（n）{@link Code_Manacher}利用已知的回文信息，让复杂度下降
P15 基础提升-滑动窗口和单调栈结构==>区别，如果是双指针寻找局部最优可以用双端队列，单指针寻找有序局部最优用单调栈
     滑动窗口 LR指针，且L不超过R，L移动N个数 R移动N个数，所以复杂度一定是O（N）
     给定数组，求窗口滑动中最大值==>利用双端队列，队列规则如下，存放元素索引位置，保证队列大到小有序，R指针变动时，塞入数据大于等于队尾，队尾弹出，一直循环，直到小于塞入当前位置索引。这意味早入队且小的数一定是失效的，所以移除。L指针变动时判断队头元素是L指针元素是否相当，相等移除队头。
     单调栈；给定数组寻找比当前位置数大的最近的左右两边。给定一个栈，维持栈底大栈顶小的规则，插入数据小则直接插入，插入数据大则弹出栈顶，弹出时候清算数据，低下有数据表示右边大位置，左边的为当前大数。直到栈为空或者小于栈顶数据。
     正数数组累计和和最小值乘积叫做指标A，给定一个数组，求子数组中指标A最大的值。==>以每个位置上的数为最小值，求指标A。然后就是求每个位置上，左右比他小的数的边界，用单调栈
P16 基础提升-二叉树的morris遍历等
P17 基础提升-大数据题目
     1,哈希函数把数据按照种类分流 2，布隆过滤器建立集合和查询，节约大量空间 3一致性哈希解决数据服务器负载管理问题 4用并查集结构解决岛问题的并行计算 5位图计较某一范围数字的出现情况， 6利用分段统计思想，进步节省大量空间 7利用堆外排序多个单元的合并
     搜索数据top100，对搜索词进行哈希分组，取每个组里面的top100用堆，再汇总成总的top100.
     40亿个数，如果最多使用1个G内存，找出出现两次的数，1，在用32+1位表示某个数字出现次数，最大大概一个G。2，hash分割不同文件，一个个汇总==>如果在40一个数找到中位数，分段统计==>根据内存大小一段数据，为2^n个，例如1024个数，arr[0]表示数字落在0-1023范围上的个数，arr[0]10亿 arr[1]累加已经21亿了，则再在arr[1]中再分段，找到第20-10，第10亿的数字
     位运算：
     有符号32位a、b,返回ab中较大那个，不用算数比较{@link com.leecode.mashib.code.Code01_GetMax}
     是否是2或者4的倍数，2：n&（n-1）==0 表示只有一个1 4：n&（n-1）==0&&（n&0x55555555）!=0 只有一个1，并且1在偶数位置上 0x55555555==>..01010100101
     用位运算实现加减乘除 {@link BitOperation}
 P18 基础提升-暴力递归上
     机器人移动    N个点 在M位置 走K步 到P点  {@link DynamicProgramming#walk}
     数组元素，为正且不重复，可以重复使用求等于目标target的方法==> {@link DynamicProgramming#moneyTarget1}
 P19 基础提升-暴力递归下
     有序表操作都是logn水平 红黑树 avl sbt ==>搜索+平衡 SBT自平衡二叉树 还有跳表==>如何搜索，小左大右；如何删除 用左子树最右的节点或者用右子树最左的节点替换当前删除节点 avl最严格平衡树
     ==》如何检查自身平衡性，新增节点，从新增的节点一直往上检测。删除节点，从替换节点位置往上检查
     四种不平衡 ll rr ==>简单直接左右旋转  lr==>先左旋后右旋 rl先右旋后左旋
     sbt：某个节点的数量大于等于其侄子最大节点的数量
     红黑树：从任意节点出发，到叶子节点黑节点数量一样多==>任何节点最长最短路径长度不超过2倍
     跳表:{@link Code02_SkipListMap}
 P20 中级提升班-1
     窗口法：
        查找有序数组大于等于某个数最左位置==>二分logn
        一个有序数组表示绳子节点，给定另一条绳子长度为K，求最多能覆盖的节点数。==>以某个点为结束，查找之前大于等于某个数最左边，则此时最大覆盖数为n-k+1 n:当前位置 k：最左位置 n*logn==>滑动窗口 lr,r滑动到窗口不大于k的位置，计算lr，l++，再计算窗口。复杂度n
     打表法:
         小虎苹果问题6n 8n;求24的余数;奇数返回，24前面就几种情况
         4的倍数，吃草问题==>b  0 后 1 先 2 后 3先4 先  暴力尝试，从1..4..16进行先手吃尝试，如果任意过程能赢则表示先手赢==>n%5==0/2为后手
     预处理法：空间换时间
        RG图颜色，最后左侧是G右侧R，从0位置尝试，当前位置之前都是G+之后位置都是R变换颜色最多的位置。辅助数组A 从0-->N-1有几个R，数组B N-1-->0有几个G，选择位置上A[i]+B[i]最小的值。
        n*n矩阵==>长方形子矩阵数量级 n^4 任意一点A（n^2）+B（n^2）组成::正方形子矩阵数量级 n^3 任意一点A（n^2）+斜点B（n）组成==>最大正方形子矩阵 新增预处理矩阵right和down表示某个位置开始,向右向下连续1的数量.
     从1-5随机函数 到1-7的随机函数 从a-b随机到c-d随机==》通过a-b函数，找到0-1等概率函数，再在d-c范围上，找到最接近2^N的输，每个位置上用0-1等概率函数==>f函数0的概率p 为1的概率1-p，等概率返回0-1，f函数调用两次返回00-11重新调用，返回01表示0，返回10表示1.
 P21 中级提升班-2
     非负正数n，表示二叉树的节点数，问一共有多少种可能二叉树==>左节点f(i)*f(n-i-1)==>动态规划dp[0]=1
     左右括号，需要几个才能使规整的。遍历一遍，左+右-，最后取绝对值
     数组中，差值为k的去重数值对。1，数组排序+遍历每个位置 n^2 2,利用hashset，数组元素加入hashset，遍历数组元素，在set中取元素+k的值，有则表示数值对。
 P22 中级提升班-3
     字符串由‘（’‘）’组成，求最长的连续合法子串长度{@link MiddleClass_03#maxLength(String)}
     数字转换字符串，1对应A,2对应B，求字符串有多少种转换类型{@link Recursion#translateNum1(int)}
     二叉树每个节点都有一个值，求从根节点到叶子节点中，权值最大为多少。
 P23 中级提升班-4
     洗衣机问题 {@link TwentyTwo} 遍历每个位置，左右两边
     矩阵的旋转 数组m [a,b] [c,d] for循环表示 一共多少组的点需要交换，m[a][b+i]::m[a+i][d]::m[c][d-i]::m[c-i][b]位置交换
     Z打印，斜线打印+方向，下一条斜线==>状态控制上下，++--或者--++，边界换方向
     螺旋打印矩阵==>四个方向+四个边界，初始是0，0，c，d
     假设s和m初始化，s=“a”,m=s;定义两个操作1,m=s；s=s+s2,s= s+m 求拼接长度n的最小步骤数==>当数据为质数的时候，只能走第二种办法。==>不为质数，进行因数分解，a*b*c 答案是a-1+b-1+c-1
     给定字符串类型数组arr,求其中次数做多的前K个==>大/小根堆==>进阶实施统计，根堆+一个map
 P24 中级提升班-5
     猫狗队列==>两个队列分别存储猫狗，队列使用相当元素，增加count时间记录先后
     栈+最小数==>栈+队列
     用队列实现栈==>两个队列，弹出的时候，把前面的元素copy到另一个队列，弹出剩余元素，如果再弹出继续copy，否则加入从尾部加入
     用栈实现队列==加入一个栈，弹出一个栈，当弹出栈为空，把加入栈倒入弹出栈
     动态规划空间压缩==>用一组数组代替全量表
     一个数组，划分数组让一边至少有一个数，求两部分最大值的差的最大的情况==>max-min(arr[0],arr[n-1])
     喝咖啡问题：arr[i]表示咖啡机冲咖啡时间，n表示多少人喝咖啡，洗咖啡杯的时间a，咖啡杯不洗自然变干净时间b。
     要求相邻德数是4的倍数。a表示奇数数量，b表示2倍数数量，c表示4倍数的数量==>b=0:a=0/1 c>=0/1 ||a>1 c>=a-1 ==>b!=0:c>=a||b=1 c>=1
 P25 中级提升班-6
     01字符串，0左边必须是1==>f(n)=f(n-1)+f(n-2)斐波拉其数列==>O(n)==>除了初始项，有严格规律，则这类问题有O(logn)解==>|f(n),f(n-1)|=|f(1),f(2)|*|ab/cd|^n-2==>求解矩阵的n-2次方==>x^y次方==>res = x^1+x^2+x^4+x^8...=>只需要求解log（n）次
     给你N根木根，第i根长度i，保留最多木棍使的不能组成三角形==>求N中有多少有多少斐波拉其数
 P26 中级提升班-7
 P27 中级提升班-8
 P28 中级提升班-9
 P29 中级提升班-10
 P30 高级进阶班-1
 P31 高级进阶班-2
 P32 高级进阶班-3
 P33 高级进阶班-4
 P34 高级进阶班-5
 P35 高级进阶班-6
 P36 高级进阶班-7
 P37 高级进阶班-8
 P38 高级进阶班-9
 P39 高级进阶班-10
 P40 高级进阶班-11
    **/

}
